#include "libServer.h"

#include "dbusCommon.h"


#include <gio/gio.h>        // GIO for dbus
#include <glib-2.0/glib.h>  // GLIB for main loop
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>




static GMainLoop *pLoop = NULL;

static RTplayGdbusExample *pSkeleton = NULL;

static int callNum = 0;


static void *run(void *);

static int thread_create(void);




/* 发送字符串 */
static gboolean Emit_My_signal1(gconstpointer p)
{
    g_print("Emit_My_Signal1() is called.\n");

    gchar buf[20];
    memset(buf, 0, 20);
    callNum++;
    sprintf(buf, "Server Signal1(%d)", callNum);

    rtplay_gdbus_example_emit_my_signal1(pSkeleton, buf);

    return TRUE;
}



/* 发送int,字符串变体 */
static gboolean Emit_My_Signal2(gconstpointer p)
{
    g_print("Emit_My_Signal2() is called.\n");

    callNum++;
    GVariant *payload = g_variant_new("(is)", callNum, "Server Signal2");

    rtplay_gdbus_example_emit_my_signal2(pSkeleton, payload);

    return TRUE;
}





/* 客户端调用方法1 */
static gboolean My_Method1(
	// 这个可以认为是客户端的影子对象， 可以通过这个对象回调函数给客户端
	RTplayGdbusExample*		object, 		
	GDBusMethodInvocation*	invocation, 
	const gchar*			in_arg)
{
    g_print("Server MyMethod1 call. Parameter: %s.\n", in_arg);

    in_arg = "Server My_Method1 to output.";

	/* 返回给客户端 */
    rtplay_gdbus_example_complete_my_method1(object, invocation, in_arg);

    return TRUE;
}




/* 客户端调用方法2 */
static gboolean My_Method2(
	RTplayGdbusExample*		object, 
	GDBusMethodInvocation*	invocation, 
	GVariant*				in_arg)
{
    gint in_arg1 = 0;
    gint in_arg2 = 0;
    gint out_arg2 = 0;
    gchar *out_arg1 = "Server MyMethod2 to output.";
    GVariant *out_arg = NULL;

    /* 从变体中取出两个int */
    g_variant_get(in_arg, "(ii)", &in_arg1, &in_arg2);

    g_print("Server MyMethod2 call. Parameter: in_arg1 = %d , in_arg2 = %d.\n", in_arg1, in_arg2);

    /* 生成si变体 */
    out_arg2 = in_arg1 + in_arg2;
    out_arg = g_variant_new("(si)", out_arg1, out_arg2);

	/* 返回给客户端 */
    rtplay_gdbus_example_complete_my_method2(object, invocation, out_arg);

    return TRUE;
}





/* 客户端断开连接 */
static void on_close_connection(
	GDBusConnection*	connection, 
	gboolean 			remote_peer_vanished, 
	GError*				error,
	gpointer 			user_data)
{
    g_print("The %s connection [ %p ] was closed!\n", (char *)user_data, connection);
}





static gboolean on_new_connection(
	GDBusServer*		server, 
	GDBusConnection*	connection, 
	gpointer 			user_data)
{
    GError *_error = NULL;
    RTplayGdbusExampleIface*	_iface;

	// 取得_iface
    _iface = RTPLAY_GDBUS_EXAMPLE_GET_IFACE(pSkeleton);
    _iface->handle_my_method1 = My_Method1;
    _iface->handle_my_method2 = My_Method2;

    //导出interface_。
    g_dbus_interface_skeleton_export(
		G_DBUS_INTERFACE_SKELETON(pSkeleton), 
		connection, RTPLAY_GDBUS_EXAMPLE_OBJECT_PATH,
		&_error
	);

    if (_error != NULL) 
	{
        g_print("Create new connection failed: [ %s ]\n", _error->message);
        g_error_free(_error);
    } 
	/* 监听断开连接 */
	else 
	{
        g_print("A new connection [ %p ] was created\n", connection);
        g_signal_connect(connection, "closed", G_CALLBACK(on_close_connection), user_data);
    }

    return TRUE;
}





/* 异步线程函数 */
void *run(void *para)
{
    g_print("run call in the server.\n");
    /** Start the Main Event Loop which manages all available sources of events */
    g_main_loop_run(pLoop);

    return ((void *)0);
}




/* 创建异步线程 */
int thread_create(void)
{
    int err;
    pthread_t thr;

    err = pthread_create(&thr, NULL, run, NULL);

    if (err != 0) 
	{
        g_print("Can't create thread: %s\n", strerror(err));
    } 
	else 
	{
        g_print("New thread created: %s\n", strerror(err));
    }

    return err;
}




/* 启动服务端 */
bool InitDBusCommunicationServer(void)
{
    GError *_error = NULL;
    GDBusServer *_server;
    gchar *_guid;
    bool bRet = TRUE;

    g_print("InitDBusCommunicationServer: Server started.\n");

    /** create main loop, but do not start it. */
    pLoop = g_main_loop_new(NULL, FALSE);

    pSkeleton = rtplay_gdbus_example_skeleton_new();

    _guid = g_dbus_generate_guid();
	
    //创建一个新的D-Bus服务器，该服务器侦听有效address中的第一个地址。
    _server = g_dbus_server_new_sync(
		"unix:abstract=gdbus_server", 
		G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS,
		_guid, 
		NULL, 
		NULL, 
		&_error
	);
	
    if (_error != NULL) 
	{
        g_print("Create new server failed: [ %s ]", _error->message);
        g_error_free(_error);
        return bRet;
    }

	/* 监听连接 */
    g_signal_connect(_server, "new-connection", G_CALLBACK(on_new_connection), NULL);
	
    /* 启动server。 */
    g_dbus_server_start(_server);

#if 0
	/* 发送信号， 客户端监听信号就回收到 */
    g_timeout_add(1000, (GSourceFunc)Emit_My_signal1, NULL);
    g_timeout_add(2000, (GSourceFunc)Emit_My_Signal2, NULL);
#endif

	/* 在异步线程中loop */
    thread_create();

    return bRet;
}




/* 退出服务端 */
bool DeinitDBusCommunicationServer(void)
{
    bool bRet = FALSE;
    if (0 != pLoop) 
	{
        g_main_loop_quit(pLoop);
        g_main_loop_unref(pLoop);
        bRet = TRUE;
    }

    return bRet;
}

